package com.skyeye;

import com.skyeye.entity.User;
import com.skyeye.mapper.UserMapperAnnotation;
import com.skyeye.util.DatabaseUtil;
import com.skyeye.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

/**
 * 使用MyBatis注解方式进行用户CRUD操作的单元测试类
 * 无需XML映射文件，SQL直接写在接口方法上
 */
public class UserMapperAnnotationTest {
    
    private SqlSession sqlSession;
    private UserMapperAnnotation userMapper;
    
    @Before
    public void setUp() {
        // 创建测试表
//        DatabaseUtil.createTestTable();
        
        // 获取SqlSession和Mapper
        sqlSession = MyBatisUtil.getSqlSession();
        userMapper = sqlSession.getMapper(UserMapperAnnotation.class);
        
        System.out.println("🚀 开始执行MyBatis注解方式CRUD测试...");
    }
    
    @After
    public void tearDown() {
        // 清空测试数据
//        DatabaseUtil.truncateTestTable();
        
        // 关闭SqlSession
        MyBatisUtil.closeSqlSession(sqlSession);
        
        System.out.println("🧹 MyBatis注解方式测试完成，清理测试数据");
    }
    
    /**
     * 测试插入用户（Create）
     */
    @Test
    public void testInsertUser() {
        // 准备测试数据
        User testUser = new User("注解用户1", "annotation1@example.com", 25, "13800138000");
        testUser.setCreateTime(LocalDateTime.now());
        testUser.setUpdateTime(LocalDateTime.now());
        
        // 执行插入
        int affectedRows = userMapper.insertUser(testUser);
        
        // 验证结果
        assertEquals("应该插入1条记录", 1, affectedRows);
        assertNotNull("用户ID应该被设置", testUser.getId());
        
        System.out.println("✅ MyBatis注解方式用户插入成功！ID: " + testUser.getId());
        System.out.println("插入的用户信息: " + testUser);
    }
    
    /**
     * 测试根据ID查询用户（Read）
     */
    @Test
    public void testSelectUserById() {
        // 先插入测试数据
        User testUser = createTestUser("注解用户2", "annotation2@example.com", 30, "13900139000");
        
        // 执行查询
        User foundUser = userMapper.selectUserById(testUser.getId());
        
        // 验证结果
        assertNotNull("应该查询到用户", foundUser);
        assertEquals("用户名应该匹配", testUser.getUsername(), foundUser.getUsername());
        assertEquals("邮箱应该匹配", testUser.getEmail(), foundUser.getEmail());
        assertEquals("年龄应该匹配", testUser.getAge(), foundUser.getAge());
        assertEquals("电话应该匹配", testUser.getPhone(), foundUser.getPhone());
        
        System.out.println("✅ MyBatis注解方式用户查询成功！");
        System.out.println("查询到的用户信息: " + foundUser);
    }
    
    /**
     * 测试根据用户名查询用户
     */
    @Test
    public void testSelectUserByUsername() {
        // 先插入测试数据
        createTestUser("注解用户3", "annotation3@example.com", 28, "13700137000");
        
        // 执行查询
        User foundUser = userMapper.selectUserByUsername("注解用户3");
        
        // 验证结果
        assertNotNull("应该查询到用户", foundUser);
        assertEquals("用户名应该匹配", "注解用户3", foundUser.getUsername());
        assertEquals("邮箱应该匹配", "annotation3@example.com", foundUser.getEmail());
        
        System.out.println("✅ MyBatis注解方式根据用户名查询成功！");
        System.out.println("查询到的用户信息: " + foundUser);
    }
    
    /**
     * 测试更新用户（Update）
     */
    @Test
    public void testUpdateUser() {
        // 先插入测试数据
        User testUser = createTestUser("注解用户4", "annotation4@example.com", 35, "13600136000");
        
        // 修改用户信息
        testUser.setEmail("annotation4_new@example.com");
        testUser.setAge(36);
        testUser.setPhone("13600136001");
        testUser.setUpdateTime(LocalDateTime.now());
        
        // 执行更新
        int affectedRows = userMapper.updateUser(testUser);
        
        // 验证结果
        assertEquals("应该更新1条记录", 1, affectedRows);
        
        // 验证更新后的数据
        User updatedUser = userMapper.selectUserById(testUser.getId());
        assertEquals("邮箱应该已更新", "annotation4_new@example.com", updatedUser.getEmail());
        assertEquals("年龄应该已更新", Integer.valueOf(36), updatedUser.getAge());
        assertEquals("电话应该已更新", "13600136001", updatedUser.getPhone());
        
        System.out.println("✅ MyBatis注解方式用户更新成功！用户ID: " + testUser.getId());
        System.out.println("更新后的用户信息: " + updatedUser);
    }
    
    /**
     * 测试删除用户（Delete）
     */
    @Test
    public void testDeleteUser() {
        // 先插入测试数据
        User testUser = createTestUser("注解用户5", "annotation5@example.com", 40, "13500135000");
        int userId = testUser.getId();
        
        // 执行删除
        int affectedRows = userMapper.deleteUserById(userId);
        
        // 验证结果
        assertEquals("应该删除1条记录", 1, affectedRows);
        
        // 验证删除后的数据
        User deletedUser = userMapper.selectUserById(userId);
        assertNull("用户应该已被删除", deletedUser);
        
        System.out.println("✅ MyBatis注解方式用户删除成功！用户ID: " + userId);
    }
    
    /**
     * 测试查询所有用户
     */
    @Test
    public void testSelectAllUsers() {
        // 插入多条测试数据
        createTestUser("注解用户A", "annotationA@example.com", 20, "13100131000");
        createTestUser("注解用户B", "annotationB@example.com", 25, "13200132000");
        createTestUser("注解用户C", "annotationC@example.com", 30, "13300133000");
        
        // 执行查询
        List<User> users = userMapper.selectAllUsers();
        
        // 验证结果
        assertEquals("应该查询到3个用户", 3, users.size());
        
        System.out.println("✅ MyBatis注解方式查询所有用户成功！");
        System.out.println("查询到的用户数量: " + users.size());
        for (User user : users) {
            System.out.println("用户信息: " + user);
        }
    }
    
    /**
     * 测试根据年龄范围查询用户
     */
    @Test
    public void testSelectUsersByAgeRange() {
        // 插入测试数据
        createTestUser("注解用户X", "annotationX@example.com", 22, "13400134000");
        createTestUser("注解用户Y", "annotationY@example.com", 23, "13500135000");
        createTestUser("注解用户Z", "annotationZ@example.com", 24, "13600136000");
        
        // 执行查询
        List<User> users = userMapper.selectUsersByAgeRange(22, 23);
        
        // 验证结果
        assertEquals("应该查询到2个用户（年龄22-23）", 2, users.size());
        
        System.out.println("✅ MyBatis注解方式根据年龄范围查询成功！");
        System.out.println("查询到的用户数量: " + users.size());
        for (User user : users) {
            System.out.println("用户信息: " + user);
        }
    }
    
    /**
     * 测试根据邮箱查询用户
     */
    @Test
    public void testSelectUserByEmail() {
        // 先插入测试数据
        createTestUser("注解测试用户", "annotationTest@example.com", 25, "13700137000");
        
        // 执行查询
        User foundUser = userMapper.selectUserByEmail("annotationTest@example.com");
        
        // 验证结果
        assertNotNull("应该查询到用户", foundUser);
        assertEquals("邮箱应该匹配", "annotationTest@example.com", foundUser.getEmail());
        
        System.out.println("✅ MyBatis注解方式根据邮箱查询成功！");
        System.out.println("查询到的用户信息: " + foundUser);
    }
    
    /**
     * 测试统计用户总数
     */
    @Test
    public void testCountUsers() {
        // 先插入测试数据
        createTestUser("注解用户AA", "annotationAA@example.com", 20, "13100131000");
        createTestUser("注解用户BB", "annotationBB@example.com", 25, "13200132000");
        
        // 执行统计
        int count = userMapper.countUsers();
        
        // 验证结果
        assertEquals("应该统计到2个用户", 2, count);
        
        System.out.println("✅ MyBatis注解方式统计用户总数成功！");
        System.out.println("用户总数: " + count);
    }
    
    /**
     * 测试根据用户名模糊查询
     */
    @Test
    public void testSelectUsersByUsernameLike() {
        // 插入测试数据
        createTestUser("注解张三", "zhangsan@example.com", 25, "13100131000");
        createTestUser("注解张四", "zhangsi@example.com", 26, "13200132000");
        createTestUser("注解李五", "liwu@example.com", 27, "13300133000");
        
        // 执行模糊查询
        List<User> users = userMapper.selectUsersByUsernameLike("张");
        
        // 验证结果
        assertEquals("应该查询到2个用户（用户名包含'张'）", 2, users.size());
        
        System.out.println("✅ MyBatis注解方式根据用户名模糊查询成功！");
        System.out.println("查询到的用户数量: " + users.size());
        for (User user : users) {
            System.out.println("用户信息: " + user);
        }
    }
    
    /**
     * 测试根据多个条件查询用户（动态SQL）
     */
    @Test
    public void testSelectUsersByConditions() {
        // 插入测试数据
        createTestUser("条件用户1", "condition1@example.com", 20, "13100131000");
        createTestUser("条件用户2", "condition2@example.com", 25, "13200132000");
        createTestUser("条件用户3", "condition3@example.com", 30, "13300133000");
        
        // 测试1：只按用户名查询
        List<User> users1 = userMapper.selectUsersByConditions("条件", null, null);
        assertEquals("应该查询到3个用户", 3, users1.size());
        
        // 测试2：按年龄范围查询
        List<User> users2 = userMapper.selectUsersByConditions(null, 20, 25);
        assertEquals("应该查询到2个用户（年龄20-25）", 2, users2.size());
        
        // 测试3：组合条件查询
        List<User> users3 = userMapper.selectUsersByConditions("条件", 20, 25);
        assertEquals("应该查询到2个用户", 2, users3.size());
        
        System.out.println("✅ MyBatis注解方式动态SQL查询成功！");
    }
    
    /**
     * 测试批量插入用户
     */
    @Test
    public void testBatchInsertUsers() {
        // 准备批量数据
        List<User> users = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            User user = new User("批量用户" + i, "batch" + i + "@example.com", 20 + i, "1380013800" + i);
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            users.add(user);
        }
        
        // 执行批量插入
        int affectedRows = userMapper.batchInsertUsers(users);
        
        // 验证结果
        assertEquals("应该插入5条记录", 5, affectedRows);
        
        // 验证数据
        List<User> allUsers = userMapper.selectAllUsers();
        assertEquals("应该查询到5个用户", 5, allUsers.size());
        
        System.out.println("✅ MyBatis注解方式批量插入成功！");
        System.out.println("批量插入的用户数量: " + affectedRows);
    }
    
    /**
     * 测试根据ID列表查询用户
     */
    @Test
    public void testSelectUsersByIds() {
        // 先插入测试数据
        User user1 = createTestUser("ID用户1", "iduser1@example.com", 20, "13100131000");
        User user2 = createTestUser("ID用户2", "iduser2@example.com", 25, "13200132000");
        User user3 = createTestUser("ID用户3", "iduser3@example.com", 30, "13300133000");
        
        // 准备ID列表
        List<Integer> ids = new ArrayList<>();
        ids.add(user1.getId());
        ids.add(user3.getId());
        
        // 执行查询
        List<User> users = userMapper.selectUsersByIds(ids);
        
        // 验证结果
        assertEquals("应该查询到2个用户", 2, users.size());
        
        System.out.println("✅ MyBatis注解方式根据ID列表查询成功！");
        System.out.println("查询到的用户数量: " + users.size());
        for (User user : users) {
            System.out.println("用户信息: " + user);
        }
    }
    
    /**
     * 辅助方法：创建测试用户并返回用户对象
     */
    private User createTestUser(String username, String email, int age, String phone) {
        User user = new User(username, email, age, phone);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        userMapper.insertUser(user);
        return user;
    }
}
